/**
 * @file 	 mfy.h
 * @brief       
 * @author 	 wenbo
 * @version  1.0
 * @date 	 2024-12-10
 * 
 * @copyright Copyright (c) 2024  WENBO
 * 
 */
#include "bsp.h"


/**
 * @brief       MFY (made for YGL) 配件认证驱动
 * 当前配件认证主要是针对 "泡沫水蜡原液" 的来源进行认证,通过认证设备读取粘贴于桶身的 RFID 标签
 * 校验其标签内数据是否符合出厂时按照预设加密方式写入的数据格式规则,认证流程的所有步骤异常消息
 * 以及卡号同步至云端,由云端(APP)进行处理.
 * 
 * 应用层初始化时创建多个认证 "handle"(例如泡沫,水蜡各需一个独立的认证主板),如果过程处理逻辑由
 * 驱动层自动处理,则无需注册事件回调.(驱动器任务可处理多个实例)
 * 
 * 应用层需增加认证设备中断IO信号的监测逻辑
 *      如果注册了回调:  
 *          在检测到触发后调用 xp_mfy_active_irq_process 将此IO 所对应的认证主板 handle 发送
 *          到驱动层处理逻辑,处理结果会回调注册的事件处理函数进行通知,在此事件回调函数中进行状态上报等操作.
 *      如果未注册回调:
 *          应用层需调用 xp_mfy_get_state() 获取状态, 调用 xp_mfy_clear_irq() 清除中断
 *          调用 xp_mfy_get_card_number() 获取卡号, 调用 xp_mfy_clear_error_code() 清错误
 * 
 * 以下是认证设备的一些状态切换
 * 
 * RFID 认证：
 *      1. 认证设备在检测到有卡后按照预设的扇区密码读出指定的加密扇区数据,如果读取失败则发出 "检测到无效卡" 事件
 *      2. 使用预设的 AES 密钥解密扇区数据,如果解密后的数据内容中卡号和当前卡号相符,则判断为检测到有效卡,转入[换入新料流程],否则发出 "检测到伪造卡" 事件
 * 
 * 换入新料：
 *      1. 检测到有效卡后跳转到下一步,(未检测到卡期间如果桶传感器触发,则发出 "桶异动" 事件)
 *      2. 判断在检测到卡期间,桶放入传感器持续稳定触发超过 1.5s (桶放置在第一槽中) 认为已检测到卡,此时发出 "检测到有效卡" 事件
 *      3. 等待旋转桶脱离传感器后进入下一步 (桶压着传感器超过 60s 认为放入超时)
 *      4. 判断桶到位第二槽条件满足后发出 "桶放入成功" 事件(卡被刺破监测不到, 桶放入传感器未被触发) (超时 30s 则发出 "桶放入异常" 事件)
 * 
 * 取出旧料：
 *      1. ARM 主板通过 modbus 发出解锁命令(可同时指定电磁锁打开的延迟时间,用于操作员准备时间)
 *      2. 认证设备收到命令后立即三声蜂鸣提示即将解锁,并且在延时指定时间后打开电磁锁(电磁锁打开时有较大响声,无需再次提示)
 *      3. 电磁锁预设的打开保持时间为 3s,在打开期间如果监测到传感器仍触发会连续蜂鸣报警,并在异常时间超过保持期间 20% 后发出 "电磁锁打开异常" 事件
 *      4. 电磁锁在保持时间到达后关闭,并且在关闭后如果检测到传感器未触发会连续蜂鸣报警,并且发出 "电磁锁关闭异常" 事件,直到传感器触发才会发出 "无异常" 事件并停止报警
 */


typedef struct Type_MFy_Def* Type_MFY_CTX;

typedef enum {
    EVT_STATE_UPDATE,
    EVT_CARD_NUMBER_REPORT,
    EVT_DI_UPDATE,
} MFY_event_t;

typedef void(*mfy_event_cb_t)(MFY_event_t evt, uint8_t state, void* data, void* user_data);

// 以下 API 为必要(xp_mfy_creat 时 cb = NULL,则驱动层不创建默认的处理任务)
/********************************************************************/

Type_MFY_CTX xp_mfy_creat(uint8_t port, uint32_t baudrate, uint8_t slave_id, mfy_event_cb_t cb, void* user_data);
void xp_mfy_del(Type_MFY_CTX ctx);
bool xp_mfy_active_irq_process(Type_MFY_CTX ctx);
bool xp_mfy_unlock(Type_MFY_CTX ctx, uint16_t elock_holdtime_ms);
const char* xp_mfy_get_state_string(uint8_t state);

/********************************************************************/

// 以下 API 除非应用层需要自行实现控制逻辑,不需要驱动层创建任务处理才需调用
/********************************************************************/

bool xp_mfy_get_io(Type_MFY_CTX ctx, uint8_t* state);
bool xp_mfy_froce_set_io(Type_MFY_CTX ctx, uint8_t pin, bool state);
bool xp_mfy_clear_irq(Type_MFY_CTX ctx);
bool xp_mfy_clear_error_code(Type_MFY_CTX ctx);
bool xp_mfy_get_card_number(Type_MFY_CTX ctx, uint32_t* card_number);
bool xp_mfy_get_state(Type_MFY_CTX ctx, uint16_t* state);

/********************************************************************/